// **********************************************************************
//
// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************

#include <Ice/Ice.h>
#include <Person.h>

using namespace std;
using namespace Demo;
using namespace IceUtil;

class CallSetAddress : public virtual Thread
{
public:

    CallSetAddress(PersonPrx& p) : _p(p)
    {
    }

    virtual void run()
    {
	try
	{
	    cout << "Calling setAddress()" << endl;
	    _p->setAddress("Elm Street");
	    cout << "setAddress() returned successfully" << endl;
	}
	catch(const ::Ice::ObjectNotExistException&)
	{
	    cout << "setAddress() raised ObjectNotExistException" << endl;
	}
	ThreadControl::sleep(Time::seconds(1));
	try
	{
	    cout << "Calling setAddress() again" << endl;
	    _p->setAddress("Elm Street");
	    cerr << "Second call to setAddress() unexpectedly succeeded!" << endl;
	    abort();
	}
	catch(const Ice::ObjectNotExistException&)
	{
	    cout << "setAddress() raised ObjectNotExistException, as expected" << endl;
	}
    }

private:

    PersonPrx _p;

};

int
main(int argc, char* argv[])
{
    int status = EXIT_SUCCESS;
    Ice::CommunicatorPtr communicator;

    try
    {
	communicator = Ice::initialize(argc, argv);
	PersonFactoryPrx pf = PersonFactoryPrx::checkedCast(communicator->stringToProxy("pf:tcp -p 10000"));
	if(!pf)
	{
	    cerr << argv[0] << ": invalid proxy" << endl;
	    status = EXIT_FAILURE;
	}
	else
	{
	    PersonPrx p = pf->create("Fred", "Elm Street");
	    ThreadPtr tp = new CallSetAddress(p);
	    tp->start();
	    ThreadControl::sleep(Time::seconds(1));
	    cout << "Calling destroy()" << endl;
	    p->destroy();
	    cout << "destroy() returned normally" << endl;
	    tp->getThreadControl().join();
	}
    }
    catch(const Ice::Exception& ex)
    {
	cerr << ex << endl;
	status = EXIT_FAILURE;
    }

    if(communicator)
    {
	try
	{
	    communicator->destroy();
	}
	catch(const Ice::Exception& ex)
	{
	    cerr << ex << endl;
	    status = EXIT_FAILURE;
	}
    }

    return status;
}
